package sqlgen

import (
	"fmt"
	"strings"
)

func dtypeConvert(dtype uint) string {
	if dtype == DTypeText {
		return "text"
	} else if dtype == DTypeInt {
		return "int"
	} else if dtype == DTypeID {
		return "text"
	} else if dtype == DTypeReal {
		return "real"
	} else {
		return "unknown"
	}
}

// GenerateLoadColumnSpecSQL generates the SQL associated with a LoadColumn
// specification
func GenerateLoadColumnSpecSQL(column *LoadColumn) string {
	colSpec := fmt.Sprintf("'%s' %s", column.Column, dtypeConvert(column.DType))

	if column.Required {
		colSpec = fmt.Sprintf("%s not null", colSpec)
	}

	if len(column.Enum) > 0 {
		enumVals := []string{}
		for _, a := range column.Enum {
			enumVals = append(enumVals, fmt.Sprintf("%d", a))
		}
		checkConstraint := fmt.Sprintf("check(%s in (%s))", column.Column, strings.Join(enumVals, ","))
		colSpec = fmt.Sprintf("%s %s", colSpec, checkConstraint)
	} else if column.Check != "" {
		checkConstraint := fmt.Sprintf("check(%s)", column.Check)
		colSpec = fmt.Sprintf("%s %s", colSpec, checkConstraint)
	}

	return colSpec
}

func GenerateLoadTableSpecCreateSQL(tableSpec *TableSpec) string {
	columnSpecs := []string{}
	for _, column := range tableSpec.Columns {
		columnSpecs = append(columnSpecs, GenerateLoadColumnSpecSQL(&column))
	}
	if len(tableSpec.UniqueSet) > 0 {
		columnSpecs = append(columnSpecs, fmt.Sprintf("unique(%s)", strings.Join(tableSpec.UniqueSet, ",")))
	}

	// TODO: If we upgrade to sqlite 3.37.0 eventually these tables could be
	// strict suffixed, until then this is.. loose
	return fmt.Sprintf(
		"create table if not exists %s (%s)",
		tableSpec.Table,
		strings.Join(columnSpecs, ","),
	)
}

func GenerateLoadTableSpecIndexSQL(tableName string, indexColumns []string) (string, string) {
	var (
		indexName = fmt.Sprintf(
			"idx_%s%d_%s",
			tableName,
			len(indexColumns),
			strings.Join(indexColumns, "_"),
		)
		createStatement = fmt.Sprintf(
			"create index %s on %s (%s)",
			indexName,
			tableName,
			strings.Join(indexColumns, ","),
		)
	)
	return indexName, createStatement
}
